package com.star.jersey.redis.autoconfig;

import com.star.jersey.redis.serialization.RedisFastJsonSerializer;
import com.star.jersey.redis.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @description: redis自动装配
 * 这个类还是很简单的, 满足指定条件下, 配置出自定义的 RedisService.
 * @ConditionalOnXxx 注解简单介绍一下, 代码中 @ConditionalOnClass(RedisService.class)
 * 当 classpath 下发现 RedisService 时才进行自动配置; @ConditionalOnMissingBean,
 * 当上下文中不存在该 Bean 时才创建;
 * @motto: 代码源于生活，高于生活艺术
 * @author: zhouhengzhe
 * @date: 2022/10/18 11:02
 * @since 1.0
 **/
@Slf4j
@Configuration
@ConditionalOnClass(RedisService.class)
public class RedisAutoConfiguration {

    private RedisTemplate<String, Object> redisTemplate;

    /**
     * value 的序列化器
     */
    private final RedisFastJsonSerializer<Object> valueRedisSerializer = new RedisFastJsonSerializer<>(Object.class);

    /**
     * @ConditionalOnMissingBean，它是修饰bean的一个注解，主要实现的是， 当你的bean被注册之后，如果而注册相同类型的bean，就不会成功，它会保证你的bean只有一个，
     * 即你的实例只有一个，当你注册多个相同的bean时，会出现异常，以此来告诉人员。(唯一性注解)
     */
    @Bean
    @ConditionalOnMissingBean
    public RedisService redisService() {
        return new RedisService(redisTemplate);
    }

    @Autowired
    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Bean
    @SuppressWarnings("all")
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        // RedisCacheWriter
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
        // RedisCacheConfiguration - 值的序列化方式
        RedisSerializationContext.SerializationPair<Object> serializationPair = RedisSerializationContext.SerializationPair.fromSerializer(valueRedisSerializer);
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(serializationPair);
        return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
    }

    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        // 配置连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        //String的序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        //key采用String的序列化方式
        redisTemplate.setKeySerializer(stringRedisSerializer);
        //hash的key也采用string的序列化方式
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        //value序列化方式采用jackson
        redisTemplate.setValueSerializer(valueRedisSerializer);
        //设置hash的value序列化方式采用jackson
        redisTemplate.setHashValueSerializer(valueRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}
